/*
 * ArchivoLexico.cpp
 *
 *  Created on: 31/03/2011
 */

#include "ArchivoLexico.h"
#include <string>

ArchivoLexico::ArchivoLexico(string unNombreDeArchivoLexico) {

	this->nombreDeArchivoLexico = unNombreDeArchivoLexico;

	//Crea el archivo y lo deja abierto en modo lectura - escritura binario
	this->archivoLexico.open(nombreDeArchivoLexico.c_str(), ios::in | ios::out | ios::binary);


	/* determina si tuvo éxito la apertura del archivo */
//	if (!this->archivoLexico.is_open()) {
//
//		/* limpia los flags de control de estado del archivo */
//		this->archivoLexico.clear();
//		throw string("El archivo no pudo ser abierto");
//	}

	this->archivoLexico.close();

}

void ArchivoLexico::abrirParaLeer() {
	//Abre el archivo y lo deja abierto en modo lectura binaria
	this->archivoLexico.open(nombreDeArchivoLexico.c_str(), ios::in  | ios::binary);

	/* determina si tuvo éxito la apertura del archivo */
	if (!this->archivoLexico.is_open()) {

		/* limpia los flags de control de estado del archivo */
		this->archivoLexico.clear();
		throw string("El archivo no pudo ser abierto para lectura");
	}
}

void ArchivoLexico::abrirParaEscribir() {
	//Abre el archivo y lo deja abierto en modo lectura binaria
	this->archivoLexico.open(nombreDeArchivoLexico.c_str(), ios::out | ios::app  | ios::binary);

	/* determina si tuvo éxito la apertura del archivo */
	if (!this->archivoLexico.is_open()) {

		/* limpia los flags de control de estado del archivo */
		this->archivoLexico.clear();
		throw string("El archivo no pudo ser abierto para lectura");
	}
}


int ArchivoLexico::escribir(RegistroLexico* unRegistroRuta) {

	//Obtengo la longitud del registro
	int longitudDelRegistro = unRegistroRuta->obtenerLongitud();

	//Me posiciono al final del archivo
	this->archivoLexico.seekp(0, ios_base::end);

	//Guardo el offset para usarlo como id al registro guardado
	int offset = this->archivoLexico.tellp();

	//Grabo como primer campo la longitud del registro
	this->archivoLexico.write((char*) &longitudDelRegistro, sizeof(int));

	//Paso el registro a binario
	char* binario = unRegistroRuta->aBinario();

	//Grabo como segundo campo el registro
	this->archivoLexico.write(binario, longitudDelRegistro);

	//Devuelvo el id al registro grabado
	return offset;

}

RegistroLexico* ArchivoLexico::leer(int idRegistroLexico) {

	/*El id del registro me da el offset donde se encuentra el
	 * primer campo a leer que es la longitud del registro */
	//Me posiciono en el campo longitud
	this->archivoLexico.seekg(idRegistroLexico, ios_base::beg);

	//Obtengo la longitud del registro
	int longitudDelRegistro;
	this->archivoLexico.read((char*) &longitudDelRegistro,sizeof(int));

	//Leo el registro en binario
	char* binario = new char[longitudDelRegistro];
	this->archivoLexico.read(binario,longitudDelRegistro);

	//Obtengo el registro ruta
	RegistroLexico* registroRuta = new RegistroLexico();
	//Convierto el registro desde binario a un objeto RegistroLexico
	registroRuta->desdeBinario(binario, longitudDelRegistro);

	return registroRuta;

}

RegistroLexico* ArchivoLexico::leerSiguiente() {

	if(this->archivoLexico.eof())
		return NULL;
	//Obtengo la longitud del registro
	int longitudDelRegistro;
	this->archivoLexico.read((char*) (&longitudDelRegistro),sizeof(int));
	//si la long es cero o mayor a 100 entonces ya no estoy en el registro
	if(longitudDelRegistro == 0)
		return NULL;

	//Leo el registro en binario
	char* binario = new char[longitudDelRegistro];
	this->archivoLexico.read(binario,longitudDelRegistro);

	//Obtengo el registro lexico
	RegistroLexico* registroLexico = new RegistroLexico();
	//Convierto el registro desde binario a un objeto RegistroLexico
	registroLexico->desdeBinario(binario, longitudDelRegistro);
	//si el primer caracter no es el asterisco entonces ya no estoy en el registro
//	if(registroLexico->obtenerLexico()[0] != '*'){
//		return NULL;
//	}

	return registroLexico;

}

void ArchivoLexico::cerrar() {
	this->archivoLexico.close();
}

ArchivoLexico::~ArchivoLexico() {
}

bool ArchivoLexico::estaCerrado(){
	return (!this->archivoLexico.is_open());
}

void ArchivoLexico::sobreescribir(){
	//Trunca el archivo
	this->archivoLexico.open(nombreDeArchivoLexico.c_str(), ios::in | ios::out | ios::trunc | ios::binary);

	this->archivoLexico.close();

}
